# coding: utf-8
from collections import deque
from typing import Callable

import requests
from PIL.ImageQt import fromqimage, toqimage
from PySide6.QtCore import QThread, Signal, QObject, QThreadPool
from PySide6.QtGui import QImage
from PySide6.QtWidgets import QLabel, QWidget


class ImageRequest:

    def __init__(
            self,
            label: QWidget,
            url: str,
            params: dict = None,
            slot: Callable = None
    ):
        self.label = label
        self.url = url
        self.params = params or {}
        self.slot = slot


class ImageResponse:

    def __init__(self, label: QLabel, image: QImage, error: str = None, slot: Callable = None):
        self.label = label
        self.image = image
        self.error = error
        self.slot = slot


class ImageSignalBus(QObject):
    fetchDataSignal = Signal(ImageRequest)
    resultSignal = Signal(ImageResponse)


imageSignalBus = ImageSignalBus()


def imageRequest(label: QWidget, url: str, params: dict = None, slot: Callable = None):
    request = ImageRequest(label, url, params, slot)
    imageSignalBus.fetchDataSignal.emit(request)


class LoadImageThread(QThread):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.queue = deque()
        self.pool = QThreadPool(self)
        self.pool.setMaxThreadCount(8)
        imageSignalBus.fetchDataSignal.connect(self.addTask)

    def run(self):
        while self.queue:
            request: ImageRequest = self.queue.popleft()
            self.pool.start(lambda: self.handleRequst(request))

    def handleRequst(self, request: ImageRequest):
        response = requests.get(request.url, **request.params)
        response.raise_for_status()
        image = QImage()
        image.loadFromData(response.content)
        imageSignalBus.resultSignal.emit(ImageResponse(request.label, image, None, request.slot))

    @classmethod
    def generatedThumbnail(cls, image: QImage, width=400):
        try:
            tmp = fromqimage(image)
            iw, ih = image.width(), image.height()
            than = ih / iw
            height = int(width * than)
            tmp.thumbnail((width, height))
            image = toqimage(tmp)
            return image
        except Exception as e:
            print(e)
            return QImage()

    def addTask(self, request: ImageRequest):
        self.queue.append(request)
        if not self.isRunning():
            self.start()
